﻿using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using PmSoft.Data.Abstractions;
using System.Data;

namespace PmSoft.Web.Abstractions.Attributes;
/// <summary>
/// 用于管理数据库事务的 Action 过滤器属性。
/// <para>
/// 将此特性应用于 Controller 或 Action 方法，以在 Action 执行期间自动开启事务。
/// 若 Action 执行成功，则提交事务；若发生异常，则回滚事务。
/// </para>
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class TransactionAttribute : Attribute, IAsyncActionFilter
{
    public TransactionAttribute()
    {
    }

	/// <summary>
	/// 获取或设置事务的隔离级别（默认: ReadCommitted）。
	/// </summary>
	public IsolationLevel IsolationLevel { get; set; } = IsolationLevel.ReadCommitted;

	// <summary>
	/// Action 执行时的异步拦截方法，用于管理事务生命周期。
	/// </summary>
	/// <param name="context">Action 执行的上下文信息。</param>
	/// <param name="next">委托，用于执行下一个过滤器或 Action 方法。</param>
	public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var unitOfWork = context.HttpContext.RequestServices.GetService<IUnitOfWork>();
        if (unitOfWork == null)
            throw new ArgumentNullException(nameof(unitOfWork));
 
        await unitOfWork.BeginTransactionAsync();

        try
        {
            var resultContext = await next();

            if (resultContext.Exception == null)
            {
                await unitOfWork.CommitTransactionAsync();
            }
            else
            {
                await unitOfWork.RollbackTransactionAsync();
            }
        }
        catch (Exception)
        {
            await unitOfWork.RollbackTransactionAsync();
            throw;
        }
    }
}